package com.qi.services.impl;

import cn.dev33.satoken.secure.BCrypt;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qi.common.RoleKey;
import com.qi.common.Status;
import com.qi.exception.ServerException;
import com.qi.mapper.ClubMapper;
import com.qi.mapper.UserMapper;
import com.qi.pojo.dto.LoginBody;
import com.qi.pojo.dto.RegisterBody;
import com.qi.pojo.dto.UpdateUserBody;
import com.qi.pojo.entity.Club;
import com.qi.pojo.entity.Role;
import com.qi.pojo.entity.Type;
import com.qi.pojo.entity.User;
import com.qi.pojo.vo.UserDetails;
import com.qi.services.IClubService;
import com.qi.services.IRoleService;
import com.qi.services.ITypeService;
import com.qi.services.IUserService;
import com.qi.utils.ImageUtil;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {

    @Resource
    private IRoleService roleService;

    @Resource
    private ClubMapper clubMapper;

    @Resource
    private ITypeService typeService;

    @Override
    public void recepLogin(LoginBody loginBody) {

        // 数据校验
        if (ObjUtil.isEmpty(loginBody)
                || StrUtil.isBlank(loginBody.getUsername())
                || StrUtil.isBlank(loginBody.getPassword())) {

            throw new ServerException("用户名或密码不能为空");
        }

        // 查询数据库
        LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(User::getUsername, loginBody.getUsername());
        User user = this.getOne(lambdaQueryWrapper);
        if (ObjUtil.isEmpty(user)) {
            throw new ServerException("用户名或密码错误");
        }

        // 密码匹配
        boolean ok = BCrypt.checkpw(loginBody.getPassword(), user.getPassword());
        if (!ok) {
            throw new ServerException("用户名或密码错误");
        }

        // 登录
        StpUtil.login(user.getUsername());
    }

    @Override
    public void adminLogin(LoginBody loginBody) {

        // 数据校验
        if (ObjUtil.isEmpty(loginBody)
                || StrUtil.isBlank(loginBody.getUsername())
                || StrUtil.isBlank(loginBody.getPassword())) {

            throw new ServerException("用户名或密码不能为空");
        }

        // 查询数据库
        LambdaQueryWrapper<User> userLambdaQueryWrapper = new LambdaQueryWrapper<>();
        userLambdaQueryWrapper.eq(User::getUsername, loginBody.getUsername());
        User user = this.getOne(userLambdaQueryWrapper);
        if (ObjUtil.isEmpty(user)) {
            throw new ServerException("用户名或密码错误");
        }

        // 密码匹配
        boolean ok = BCrypt.checkpw(loginBody.getPassword(), user.getPassword());
        if (!ok) {
            throw new ServerException("用户名或密码错误");
        }

        // 角色匹配（社员和游客无法登录后台系统）
        Role role = roleService.getById(user.getRoleId());
        String roleKey = role.getRoleKey();
        if (StrUtil.equals(roleKey, "SUPER_ADMIN")
                || StrUtil.equals(roleKey, "CLUB_ADMIN")) {

            // 登录
            StpUtil.login(user.getUsername());
            return;
        }

        throw new ServerException(Status.PERMISSION_MISMATCHED);
    }

    @Override
    public void register(RegisterBody registerBody) {
        // 参数校验
        if (ObjUtil.isEmpty(registerBody)
                || StrUtil.isBlank(registerBody.getUsername())
                || StrUtil.isBlank(registerBody.getPassword())) {

            throw new ServerException("至少用户名密码不能为空");
        }
        // 构造用户对象
        User user = new User();
        BeanUtil.copyProperties(registerBody, user);
        user.setClubId(0L);
        // 查询数据库（确保唯一）
        LambdaQueryWrapper<User> userLambdaQueryWrapper = new LambdaQueryWrapper<>();
        userLambdaQueryWrapper.eq(User::getUsername, user.getUsername());
        User existUser = this.getOne(userLambdaQueryWrapper);
        if (ObjUtil.isNotEmpty(existUser)) {
            throw new ServerException("用户名已存在");
        }
        // 密码加密
        String hashPw = BCrypt.hashpw(user.getPassword(), BCrypt.gensalt());
        user.setPassword(hashPw);
        // 分配角色
        LambdaQueryWrapper<Role> roleLambdaQueryWrapper = new LambdaQueryWrapper<>();
        roleLambdaQueryWrapper.eq(Role::getRoleName, "游客");
        Role role = roleService.getOne(roleLambdaQueryWrapper);
        user.setRoleId(role.getId());
        // 插入数据库
        boolean userSaved = this.save(user);
        if (!userSaved) {
            throw new ServerException("用户数据添加失败");
        }
    }

    @Override
    public UserDetails getCurUser() {
        User curUser = this.getCurUserInfo();
        // 查询角色信息
        Role role = roleService.getById(curUser.getRoleId());

        Club club = null;
        if (ObjUtil.isNotEmpty(curUser.getClubId())
                && !ObjUtil.equals(curUser.getClubId(), 0L)) {
            // 查询社团信息
            club = clubMapper.selectById(curUser.getClubId());
            // 查询社团类型
            Type type = typeService.getById(club.getTypeId());
            club.setType(type);
            // 设置社长信息
            User president = this.getById(club.getPresidentId());
            club.setPresident(president.getName());
            // 设置社团照片
            club.setImage(ImageUtil.getImageBase64(club.getImageLocation()));
        }
        // 构造返回结果对象
        UserDetails userDetails = new UserDetails();
        BeanUtil.copyProperties(curUser, userDetails);
        userDetails.setClub(club);
        userDetails.setRole(role);
        return userDetails;
    }

    @Override
    public User getCurUserInfo() {
        String username = StpUtil.getLoginIdAsString();
        LambdaQueryWrapper<User> userLambdaQueryWrapper = new LambdaQueryWrapper<>();
        userLambdaQueryWrapper.eq(User::getUsername, username);
        return this.getOne(userLambdaQueryWrapper);
    }

    @Override
    public UserDetails getUserDetailsByUserId(Long userId) {
        // 查询用户信息
        User user = this.getById(userId);
        if (ObjUtil.isEmpty(user)) {
            throw new ServerException("用户不存在");
        }
        // 查询角色信息
        Role role = roleService.getById(user.getRoleId());

        Club club = null;
        if (!ObjUtil.equals(user.getClubId(), 0L)) {
            // 查询社团信息
            club = clubMapper.selectById(user.getClubId());
            // 查询社团类型
            Type type = typeService.getById(club.getTypeId());
            club.setType(type);
        }
        // 构造返回结果对象
        UserDetails userDetails = new UserDetails();
        BeanUtil.copyProperties(user, userDetails);
        userDetails.setClub(club);
        userDetails.setRole(role);
        return userDetails;
    }

    @Override
    public List<User> userList(String name, String gender) {
        // 查询角色信息
        List<String> roleKeyList = new ArrayList<>();
        roleKeyList.add(RoleKey.超级管理员);
        roleKeyList.add(RoleKey.社团管理员);
        LambdaQueryWrapper<Role> roleLambdaQueryWrapper = new LambdaQueryWrapper<Role>().in(Role::getRoleKey, roleKeyList);
        List<Long> roleIdList = roleService.list(roleLambdaQueryWrapper).stream().map(Role::getId).toList();
        // 定义查询规则
        LambdaQueryWrapper<User> userLambdaQueryWrapper = new LambdaQueryWrapper<User>()
                .like(!StrUtil.isBlank(name), User::getName, name)
                .like(!StrUtil.isBlank(gender), User::getGender, gender)
                .notIn(User::getRoleId, roleIdList);
        return this.list(userLambdaQueryWrapper);
    }

    @Override
    public IPage<User> userListPage(Long page, Long size, String name, String gender) {
        User president = this.getCurUserInfo();
        IPage<User> userPage = new Page<>(page, size);
        // 定义查询规则
        LambdaQueryWrapper<User> userLambdaQueryWrapper = new LambdaQueryWrapper<User>()
                .like(!StrUtil.isBlank(name), User::getName, name)
                .like(!StrUtil.isBlank(gender), User::getGender, gender)
                .eq(User::getClubId, president.getClubId());
        // 查询
        userPage = this.page(userPage, userLambdaQueryWrapper);
        // 设置角色信息
        for (User user : userPage.getRecords()) {
            Role role = roleService.getById(user.getRoleId());
            user.setRoleName(role.getRoleName());
        }
        return userPage;
    }

    @Override
    public List<User> nativeUserList(String name, String gender) {
        User president = this.getCurUserInfo();
        // 定义查询规则
        LambdaQueryWrapper<User> userLambdaQueryWrapper = new LambdaQueryWrapper<User>()
                .like(!StrUtil.isBlank(name), User::getName, name)
                .like(!StrUtil.isBlank(gender), User::getGender, gender)
                .eq(User::getClubId, president.getClubId());
        // 查询
        List<User> userList = this.list(userLambdaQueryWrapper);
        // 设置角色信息
        for (User user : userList) {
            Role role = roleService.getById(user.getRoleId());
            user.setRoleName(role.getRoleName());
        }
        return userList;
    }

    @Override
    public void setRole(Long userId, String roleKey) {
        LambdaQueryWrapper<Role> roleQueryWrapper = new LambdaQueryWrapper<Role>().eq(Role::getRoleKey, roleKey);
        Long roleId = roleService.getOne(roleQueryWrapper).getId();
        LambdaUpdateWrapper<User> userUpdateWrapper = new LambdaUpdateWrapper<User>()
                .set(User::getRoleId, roleId)
                .eq(User::getId, userId);
        this.update(userUpdateWrapper);
    }

    @Override
    public void modify(UpdateUserBody updateUserBody) {
        User user = this.getById(updateUserBody.getId());
        if (StrUtil.isBlank(updateUserBody.getPassword())
                && ObjUtil.equals(user.getName(), updateUserBody.getName())
                && ObjUtil.equals(user.getGender(), updateUserBody.getGender())
                && ObjUtil.equals(user.getPhone(), updateUserBody.getPhone())
                && ObjUtil.equals(user.getEmail(), updateUserBody.getEmail())) {

            throw new ServerException("没有编辑任何内容，无需修改");
        }
        String hashPw = null;
        if (!StrUtil.isBlank(updateUserBody.getPassword())) {
            // 密码加密
            hashPw = BCrypt.hashpw(updateUserBody.getPassword(), BCrypt.gensalt());
        }
        LambdaUpdateWrapper<User> updateWrapper = new LambdaUpdateWrapper<User>()
                .set(!StrUtil.isBlank(hashPw), User::getPassword, hashPw)
                .set(!ObjUtil.equals(user.getName(), updateUserBody.getName()), User::getName, updateUserBody.getName())
                .set(!ObjUtil.equals(user.getGender(), updateUserBody.getGender()), User::getGender, updateUserBody.getGender())
                .set(!ObjUtil.equals(user.getPhone(), updateUserBody.getPhone()), User::getPhone, updateUserBody.getPhone())
                .set(!ObjUtil.equals(user.getEmail(), updateUserBody.getEmail()), User::getEmail, updateUserBody.getEmail())
                .eq(User::getId, updateUserBody.getId());

        this.update(updateWrapper);
    }

    @Override
    public void kickOut(Long userId) {
        LambdaUpdateWrapper<User> updateWrapper = new LambdaUpdateWrapper<User>()
                .set(User::getClubId, 0L)
                .eq(User::getId, userId);
        this.setRole(userId, RoleKey.游客);
        this.update(updateWrapper);
    }
}
